<?php
App::uses('AppController', 'Controller');
/**
 * Users Controller
 *
 * @property User $User
 */
class UsersController extends AppController {

//TODO SQL injection preventing
//TODO dealing with special characters
//TODO add application and flownode shall NOT fill the `approved time` automatically
//TODO limit application id greater than 0 through constraint

	public function beforeFilter() {
		//TODO 'preventing unlogin users' might don't work
		parent::beforeFilter();
		$this->Auth->allow('add', 'logout');
	}

/**
 * index method
 *
 * @return void
 */
	public function index() {
		echo ($this->Auth->User('id'));
		$this->User->recursive = 0;
		$this->set('users', $this->paginate());
	}

/**
 * view method
 *
 * @param string $id
 * @return void
 */
	public function view($id = null) {
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		$this->set('user', $this->User->read(null, $id));
	}

/**
 * add method
 *
 * @return void
 */

	public function add() {
		if ($this->request->is('post')) {
			$this->User->create();
			if ($this->User->findByUsername($this->request->data['User']['username'])) {
				$this->Session->setFlash(__('The username %s already exists', $this->request->data['User']['username']));
				$this->redirect(array('action' => 'add'));
			} else {
				if ($this->User->save($this->request->data)) {
					$this->Auth->login($this->request->data);
					$this->Session->setFlash(__('The user has been saved'));
					$this->redirect(array('action' => 'index'));
				} else {
					$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
				}
			}
		}
	}

/**
 * edit method
 *
 * @param string $id
 * @return void
 */
	public function edit($id = null) {
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		if ($this->request->is('post') || $this->request->is('put')) {
			if ($this->User->save($this->request->data)) {
				$this->Session->setFlash(__('The user has been saved'));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
			}
		} else {
			$this->request->data = $this->User->read(null, $id);
		}
	}

/**
 * delete method
 *
 * @param string $id
 * @return void
 */
	public function delete($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		if ($this->User->delete()) {
			$this->Session->setFlash(__('User deleted'));
			$this->redirect(array('action' => 'index'));
		}
		$this->Session->setFlash(__('User was not deleted'));
		$this->redirect(array('action' => 'index'));
	}

/**
 * login method
 * @return void
 */
	public function login() {
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				$this->redirect($this->Auth->redirect());
			} else {
				$this->Session->setFlash(__('Invalid username or password, try again'));
			}
		}
	}
	
/**
 * logout method
 * @return void
 */
 
	public function logout() {
		$this->redirect($this->Auth->logout());
	}
	
	public function addApplication() {
		if ($this->request->is('post')) {
			if (isset($this->data['template_id']) && is_numeric($this->data['template_id']) && is_int((int)$this->data['template_id'])) {
				$template = $this->User->Application->find('first',
					array(
						'conditions' => array('Application.id' => $this->data['template_id']),
						'recursive'	=> 1 
					)
				);

				// return false if not find
				if (!$template || $template['Application']['template_pointer'] != 0) {
					$this->Session->setFlash(__('The Application# %s is not an valid template', $template['Application']['id']));
					$this->redirect(array('action' => 'addApplication'));
				}
				// add application according to the template

				$newApplication['Application'] = array(
					'user_id' => $this->Auth->User('id'),
					'summary' => $template['Application']['summary'],
					'final_status' => $template['Application']['final_status'],
					'status' => 1,
					'template_pointer' => $template['Application']['id'],
				);

				$newApplication['Flownode'] = array();
				//TODO check final_status == max{flownode['loc_identity']}
				foreach ($template['Flownode'] as $flownode){
					$newApplication['Flownode'][] = array(
						//TODO exception when specified approver Does not exist anymore
						'user_id' => $flownode['user_id'],
						'loc_index' => $flownode['loc_index'],
						'loc_identity' => $flownode['loc_identity'],
						'status' => 0
					);
				}

				if ($this->User->Application->saveAssociated($newApplication)) {
					$this->Session->setFlash('An Application has been added successfully.');
					$this->redirect(array('action' => 'index'));
				} else {
					$this->Session->setFlash('The Application could not be saved.');
					$this->redirect(array('action' => 'index'));
				}
			} else {
				// This section won't check validity of data for it's a temporary version
				if ($this->__addTemplate()) {
				} else {
					//$this->Session->setFlash("Invalid template_id or invalid template form");
					//$this->redirect(array("action" => "addApplication"));
				}
			}
		} else {
			$templateList = $this->User->Application->find('all',
				array(
					'conditions' => array('Application.template_pointer' => '0'),
					'recursive' => 1
				)
			);
			$this->set("templateList", $templateList);
		}
	}

/**
 * add template method(all flownode included)
 * @return void
 */

	//TODO assert: A user won't appear in the same Flownode.loc_index with 2 or above different Flownode.loc_identity
	public function __addTemplate() {
		$final_status = 0;
		foreach ($this->data['Flownode'] as $flownode) {
			$final_status = $final_status < $flownode['loc_index'] ? $flownode['loc_index'] : $final_status;
		}

		$this->User->Application->create();
		$this->request->data['Application']['user_id'] = $this->Auth->user('id');
		$this->request->data['Application']['status'] = 1;
		$this->request->data['Application']['template_pointer'] = 0;
		$this->request->data['Application']['final_status'] = $final_status;

		if ($this->User->Application->saveAssociated($this->request->data)) {
			$this->Session->setFlash("A template has been added successfully");
			$this->redirect(array("action" => "addApplication"));
		} else {
			return false;
		}
	}

/**
 * get all the applications submitted&not finished by current user
 *
 * @return void
 */

	// status == 0 => 'application is denied'
	// status < final_status => 'application is waiting to be approved'
	// status == final_status => 'application is approved'

	public function getWaitingApprovedApplications() {
		$this->User->Application->recursive = 0;
		//TODO limit 20
		$applicationsBySubmitter = $this->paginate("Application",
			array(
				'Application.user_id' => $this->Auth->User('id'),
				'AND' => array(
					'`Application.status` < `Application.final_status`',
					'`Application.status` > 0'
				)
			)
		);
		$this->set('applicationsBySubmitter', $applicationsBySubmitter);
	}

/**
 * get all the flownodes with applications which shall be approved/disapproved by current user
 *
 * @return void
 */

	public function getPendingApprovedFlownodes() {
		$this->User->Flownode->recursive = 0;
		$rawFlownodesByApprover = $this->User->Flownode->find('all', 
			array(
				'conditions' => array('Flownode.user_id' => $this->Auth->User('id')),
				'order' => array('Flownode.application_id' => 'asc')
			));

		$flownodesByApprover = array();
		foreach ($rawFlownodesByApprover as $flownode) {
			if ($flownode['Application']['status'] == $flownode['Flownode']['loc_index']) {
				array_push($flownodesByApprover, $flownode);
			}
		}
		$this->set('flownodesByApprover', $flownodesByApprover);
	}
	
/**
 * approve a flownode 
 *
 * @return void
 */
	
	public function approveFlownode($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$this->User->Flownode->recursive = 0;
		$this->User->Flownode->id = $id;
		if ($this->User->Flownode->exists()) {
			$flownode = $this->User->Flownode->read(null, $id);
			if ($flownode['Application']['status'] == $flownode['Flownode']['loc_index']) {
				$flownode['Flownode']['status'] = '1';
				$parallelFlownode = $this->User->Flownode->Application->Flownode->find('all', 
					array(
						'conditions' => array(
							'loc_index' => $flownode['Flownode']['loc_index'],
							'Flownode.status' => '0',
							'NOT' => array(
								'loc_identity' => $flownode['Flownode']['loc_identity']
							)
						)
					));	
				if (!$parallelFlownode) {
					 ++$flownode['Application']['status']; //next stage
				}
				$this->User->Flownode->saveAssociated($flownode);
				$this->redirect(array('controller' => 'users', 'action' => 'getPendingApprovedFlownodes'));
			} else {
				//status has already been skipped
			}
		} else {
			throw new NotFoundException(__('Invalid application'));
		}
	}
	
	public function isAuthorized($user) {
		if ($this->action == 'getPendingApprovedFlownodes' 
			|| $this->action == 'addApplication' 
			|| $this->acction == 'addTemplate') {
			return true;
		}
        return parent::isAuthorized($user);
    }
}
